#include "CMyGameBase.h"
#include "GameLayer.h"

using namespace cocos2d;

static const char g_chDir[] = {'l', 'r', 'u', 'd'};
static const int g_nDirOffX[] = {-1, 1, 0,  0};
static const int g_nDirOffY[] = { 0, 0, 1, -1};

CMyGameBase::CMyGameBase(void)
{
	m_pGame = NULL;
	init();
}

CMyGameBase::CMyGameBase(GameLayer *pGame)
{
	m_pGame = pGame;
	init();
}

CMyGameBase::~CMyGameBase(void)
{
	if (m_pCurrAni)
		m_pCurrAni->release();
}

bool CMyGameBase::init(void)
{
	CCSprite::init();
	m_pCurrAni = NULL;
	m_nType = DUMMY_VAL;
	m_nStatus = DUMMY_VAL;
	m_bFrameStart = true;
	m_bFrameEnd = false;
	m_nDir = 0;
	m_nOldDir = 0;
	m_bStillFrame = false;
	m_nSpeed = 0;
	setScore(0);
	m_nBBMarginLeft_Rel = m_nBBMarginLeft_Abs = 0;
	m_nBBMarginRight_Rel = m_nBBMarginRight_Abs = 0;
	m_nBBMarginFwd_Rel = m_nBBMarginUp_Abs = 0;
	m_nBBMarginBack_Rel = m_nBBMarginDown_Abs = 0;
	return true;
}

void CMyGameBase::updateObject(void)
{
	if (m_pCurrAni && !m_bStillFrame)
		m_bFrameStart = m_bFrameEnd = m_pCurrAni->nextFrame();
	if (m_bStillFrame)
		m_bFrameStart = m_bFrameEnd = true;
}

bool CMyGameBase::canHit(void)
{
	return true;
}

void CMyGameBase::setType(int type)
{
	m_nType = type;
}

int CMyGameBase::getType(void)
{
	return m_nType;
}

void CMyGameBase::setStatus(int status)
{
	m_nStatus = status;
}

int CMyGameBase::getStatus(void)
{
	return m_nStatus;
}

void CMyGameBase::setDir(int dir)
{
	m_nOldDir = m_nDir;
	m_nDir = dir;
	// set absolute-margin
	switch (m_nDir)
	{
		case DIR_LEFT :
			m_nBBMarginLeft_Abs = m_nBBMarginFwd_Rel;
			m_nBBMarginRight_Abs = m_nBBMarginBack_Rel;
			m_nBBMarginUp_Abs = m_nBBMarginRight_Rel;
			m_nBBMarginDown_Abs = m_nBBMarginLeft_Rel;
			break;

		case DIR_RIGHT :
			m_nBBMarginLeft_Abs = m_nBBMarginBack_Rel;
			m_nBBMarginRight_Abs = m_nBBMarginFwd_Rel;
			m_nBBMarginUp_Abs = m_nBBMarginLeft_Rel;
			m_nBBMarginDown_Abs = m_nBBMarginRight_Rel;
			break;

		case DIR_UP :
			m_nBBMarginLeft_Abs = m_nBBMarginLeft_Rel;
			m_nBBMarginRight_Abs = m_nBBMarginRight_Rel;
			m_nBBMarginUp_Abs = m_nBBMarginFwd_Rel;
			m_nBBMarginDown_Abs = m_nBBMarginBack_Rel;
			break;

		case DIR_DOWN :
			m_nBBMarginLeft_Abs = m_nBBMarginRight_Rel;
			m_nBBMarginRight_Abs = m_nBBMarginLeft_Rel;
			m_nBBMarginUp_Abs = m_nBBMarginBack_Rel;
			m_nBBMarginDown_Abs = m_nBBMarginFwd_Rel;
			break;
	}
}

int CMyGameBase::getDir(void)
{
	return m_nDir;
}

void CMyGameBase::setAnimation(CMyAnimInfo *pAni, bool bFlip, bool bAutoStart)
{
	if (m_pCurrAni)
	{
		m_pCurrAni->release();
		m_pCurrAni = NULL;
	}
	m_pCurrAni = (CMyAnimInfo *)pAni->copy();
	if (m_pCurrAni)
	{
		m_pCurrAni->reset();
		m_pCurrAni->setPlay(bAutoStart);
	}
	m_bFrameStart = true;
	setCurrentFrame(bFlip);
}

bool CMyGameBase::checkHitTarget(CMyGameBase *pTarget)
{
	CCPoint s_anchor = getAnchorPoint();
	CCPoint t_anchor = pTarget->getAnchorPoint();
	float s_width = getContentSize().width;
	float s_height = getContentSize().height;
	float t_width = pTarget->getContentSize().width;
	float t_height = pTarget->getContentSize().height;

	CCRect s_rc;
	s_rc.origin.x = getPositionX() - s_width * s_anchor.x + m_nBBMarginLeft_Abs;
	s_rc.origin.y = getPositionY() - s_height * s_anchor.y + m_nBBMarginUp_Abs;
	s_rc.size.width = s_width - m_nBBMarginLeft_Abs - m_nBBMarginRight_Abs;
	s_rc.size.height = s_height - m_nBBMarginUp_Abs - m_nBBMarginDown_Abs;

	CCRect t_rc;
	t_rc.origin.x = pTarget->getPositionX() - t_width * t_anchor.x + pTarget->getBBMarginAbs(DIR_LEFT);
	t_rc.origin.y = pTarget->getPositionY() - t_height * t_anchor.y + pTarget->getBBMarginAbs(DIR_UP);
	t_rc.size.width = t_width - pTarget->getBBMarginAbs(DIR_LEFT) - pTarget->getBBMarginAbs(DIR_RIGHT);
	t_rc.size.height = t_height - pTarget->getBBMarginAbs(DIR_UP) - pTarget->getBBMarginAbs(DIR_DOWN);

	return s_rc.intersectsRect(t_rc);
}

bool CMyGameBase::isPlaceOnDir(CMyGameBase *pTarget, int dir)
{
	bool ret = false;
	int dx = pTarget->getPositionX() - this->getPositionX();
	int dy = pTarget->getPositionY() - this->getPositionY();

	switch (dir)
	{
		case DIR_LEFT :
			if (dx < 0) ret = true;
			break;

		case DIR_RIGHT :
			if (dx > 0) ret = true;
			break;

		case DIR_UP :
			if (dy > 0) ret = true;
			break;

		case DIR_DOWN :
			if (dy < 0) ret = true;
			break;
	}
	return ret;
}

void CMyGameBase::setCurrentFrame(bool bFlip)
{
	if (m_pCurrAni)
	{
		setDisplayFrame(m_pCurrAni->getCurrentFrame());
		setFlipX(bFlip);
	}
}

void CMyGameBase::startAnim(void)
{
	if (m_pCurrAni)
		m_pCurrAni->setPlay(true);
}

void CMyGameBase::stopAnim(void)
{
	if (m_pCurrAni)
		m_pCurrAni->setPlay(false);
}

bool CMyGameBase::isAniOver(void)
{
	if (m_pCurrAni)
		return m_pCurrAni->isAniOver();
	return true;
}

bool CMyGameBase::checkFrameStart(void)
{
	return m_bFrameStart;
}

void CMyGameBase::clearFrameStart(void)
{
	m_bFrameStart = false;
}

bool CMyGameBase::checkFrameEnd(void)
{
	return m_bFrameEnd;
}

void CMyGameBase::clearFrameEnd(void)
{
	m_bFrameEnd = false;
}

void CMyGameBase::setMoveOffset(float dx, float dy)
{
	m_fDX = dx;
	m_fDY = dy;
}

void CMyGameBase::getNextPos(CCPoint *pos, int dir)
{
	pos->x = getPositionX() + g_nDirOffX[dir] * m_nSpeed;
	pos->y = getPositionY() + g_nDirOffY[dir] * m_nSpeed;
}

void CMyGameBase::getNameWithDir (char *szSrc, int dir, char *szOut)
{
	sprintf (szOut, "%s_%c", szSrc, g_chDir[dir]);
}

void CMyGameBase::setBBMarginRel(int l, int r, int f, int b)
{
	if (l != -1) m_nBBMarginLeft_Rel = l;
	if (r != -1) m_nBBMarginRight_Rel = r;
	if (f != -1) m_nBBMarginFwd_Rel = f;
	if (b != -1) m_nBBMarginBack_Rel = b;
	setDir(m_nDir);
}

int CMyGameBase::getBBMarginAbs(int dir)
{
	int ret = 0;

	if (dir == DIR_LEFT) ret = m_nBBMarginLeft_Abs;
	if (dir == DIR_RIGHT) ret = m_nBBMarginRight_Abs;
	if (dir == DIR_UP) ret = m_nBBMarginUp_Abs;
	if (dir == DIR_DOWN) ret = m_nBBMarginDown_Abs;

	return ret;
}

void CMyGameBase::setMoveDir(int dir)
{
	if (dir != -1 && m_nMoveDir != dir)
	{
		m_fMoveStartPos = this->getPosition();
		m_fMoveStartTime = GameLayer::getTimeTick();
		m_nOldDir = m_nDir;
		m_nDir = dir;
	}
	m_nMoveDir = dir;
}

void CMyGameBase::setVelocity(float v)
{
		m_fMoveStartPos = this->getPosition();
		m_fMoveStartTime = GameLayer::getTimeTick();
	m_fVelocity = v;
}

void CMyGameBase::calcNextMove(void)
{
	float curr = GameLayer::getTimeTick();
	float movePixels = m_fVelocity * (curr - m_fMoveStartTime) / 1000.0;

	CCLog("movePixels : %f", movePixels);
	setPositionX(m_fMoveStartPos.x + movePixels * g_nDirOffX[m_nMoveDir]);
	setPositionY(m_fMoveStartPos.y + movePixels * g_nDirOffY[m_nMoveDir]);
}
